#ifndef __TWITCH__
#define __TWITCH__

#include <windows.h>
#include "irc.h"
#include "base/array.h"
#include "base/dictionary.h"
#include "frameui/image.h"
#include "pcre/pcrecpp.h"

class MainWnd;

#define TCM_DISCONNECTED      (WM_USER+100)

struct UserInfo
{
  enum {sAdmin,
        sBroadcaster,
        sMod,
        sStaff,
        sTurbo,
        sSubscriber,

        sCount
  };
  enum {fAdmin = (1 << sAdmin),
        fBroadcaster = (1 << sBroadcaster),
        fMod = (1 << sMod),
        fStaff = (1 << sStaff),
        fTurbo = (1 << sTurbo),
        fSubscriber = (1 << sSubscriber),
  };
  uint32 special;
  uint32 color;
  Array<int> emoteset;
};
struct EmoticonImage
{
  int width;
  int height;
  String url;
  Image* image;
  int emoteset;
  EmoticonImage()
    : image(NULL)
  {}
  ~EmoticonImage()
  {
    delete image;
  }
  Image* getImage();
};
struct Emoticon
{
  pcrecpp::RE* prog;
  Array<EmoticonImage> images;
  Emoticon()
    : prog(NULL)
  {}
  ~Emoticon()
  {
    delete prog;
  }

  EmoticonImage* getImage(Array<int> const* emoteset);
};

struct ChannelInfo
{
  String title;
  String logourl;
  Image* logo;
  int viewers;

  static uint32 hash(ChannelInfo* info);
};

class TwitchClient
{
  MainWnd* mainWnd;
  IRC irc;
  String userName;
  String channelName;

  mutable UserInfo defaultUser;
  Dictionary<UserInfo> users;
  Array<Emoticon>* emoticons;

  Dictionary<Image*> images;
  Image* getImage(char const* url);

  ChannelInfo info;
  CRITICAL_SECTION infoLock;
  HANDLE infoThread;
  static DWORD WINAPI infoFunc(LPVOID arg);

  bool stopLoading;

  Image* specialIcons[UserInfo::sCount];

  HANDLE emoteLoadThread;
  HANDLE ircLoopThread;
  static DWORD WINAPI ircLoopFunc(LPVOID arg);
  static DWORD WINAPI emoteLoadFunc(LPVOID arg);
  static int onPrivMsg(char const* msg, irc_reply_data* data, IRC* irc, void* opaque);
  static int onMode(char const* msg, irc_reply_data* data, IRC* irc, void* opaque);
  static int onNotice(char const* msg, irc_reply_data* data, IRC* irc, void* opaque);
  static int on001(char const* msg, irc_reply_data* data, IRC* irc, void* opaque);
public:
  TwitchClient();
  ~TwitchClient();

  void setMainWnd(MainWnd* p)
  {
    mainWnd = p;
  }

  void connect(char const* name, char const* pass, char const* channel, uint32 port = 6667);
  void disconnect();

  void send(char const* msg);

  void updateInfo();
  ChannelInfo* getInfo();

  UserInfo const* getUserInfo(char const* name) const;

  Image const* getSpecialIcon(int id) const
  {
    if (id < 0 || id >= sizeof specialIcons / sizeof specialIcons[0]) return NULL;
    return specialIcons[id];
  }

  Array<Emoticon>* getEmoticons()
  {
    return emoticons;
  }
};

#endif // __TWITCH__
